﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace fes
{
    // Money Flow index
    // http://www.mbank.pl/indywidualny/inwestycje/emakler/encyklopedia/WSKAZNIKI/mfi.html
    class MFI : Indicator, IIndicator
    {
        private int n = 0;
        private List<double> closePrices;
        private List<double> highPrices;
        private List<double> lowPrices;
        private List<double> volumes;
        private double currentValue = -1;

        public MFI(Dictionary<String, Object> parameters): base("MFI")
        {
            base.setInidicatorParams(parameters);
            n = (int)parameters["n"] + 1;
            closePrices = new List<double>();
            highPrices = new List<double>();
            lowPrices = new List<double>();
        }

        public override void pushNextDayData(double open, double high, double low, double close, int vol)
        {
            closePrices.Add(close);
            highPrices.Add(high);
            lowPrices.Add(low);
            volumes.Add(vol);
            if (closePrices.Count > n)
            {
                closePrices.RemoveAt(0);
                highPrices.RemoveAt(0);
                lowPrices.RemoveAt(0);
                volumes.RemoveAt(0);
            }
            calculateMFI();
        }

        public void setParameters(Dictionary<String, Object> parameters)
        {

            base.setInidicatorParams(parameters);
            n = (int)parameters["n"] + 1;
        }

        public override double getValue()
        {
            return currentValue;
        }

        private void calculateMFI()
        {
            double[] typicalPrice;
            double[] rawMoneyFlow;
            double pMF = 0; //positive money flow
            double nMF = 0; //negative money flow
            double moneyRatio = 0;
            double moneyFlowIndex = 0; //Money Flow Index - calculated indicator
            int cnt = 0;

            if (closePrices.Count == n)
            {
                cnt = closePrices.Count;
                typicalPrice = new double[cnt];
                rawMoneyFlow = new double[cnt];

                for (int i = 0; i < cnt; i++)
                {
                    typicalPrice[i] = (highPrices[i] + lowPrices[i] + closePrices[i]) / 3;
                    rawMoneyFlow[i] = typicalPrice[i] * volumes[i];
                    if (i > 0)
                    {
                        if (typicalPrice[i] > typicalPrice[i - 1])
                        {
                            pMF = pMF + rawMoneyFlow[i];
                        }
                        else
                        {
                            nMF = nMF + rawMoneyFlow[i];
                        }
                    }
                }

                if (nMF > 0)
                {
                    moneyRatio = pMF / nMF;
                }
                else
                {
                    moneyRatio = 0;
                }
                moneyFlowIndex = 100 - (100 / (1 + moneyRatio));
                currentValue = moneyFlowIndex;
            }
            else
            {
                currentValue = -1;
            }
        }
    }
}
